/*LICENSE_BEGIN
 * ******************************************************************
 * All original parts of SoccerScope2003 have copyright (2003) by
 * Team YowAI, represented by Mr. Shuhei Shiota
 * The Department of Creative Informatics
 * The Graduate School of Information Science and Technology
 * The University of Tokyo
 * 
 * Additional classes (except libraries in /lib) were developed by 
 * the Dainamite Robocup-Team of the DAI-Labor, TU-Berlin 
 * (www.dai-labor.de)
 * 
 * Extended/new classes/packages are:
 *   soccerscope.analyzer.LogfileAnalyzer
 *   soccerscope.daistatistic.*
 *   soccerscope.daistatistic.charts.*
 *   soccerscope.daistatistic.tools.*
 *   soccerscope.db.*
 *   soccerscope.dialog.*
 *   soccerscope.model.PlayerWorldModel
 *   soccerscope.model.SimplePlayer
 *   soccerscope.net.AgentConnector
 *   soccerscope.training.*
 *   soccerscope.training.conditions.*
 * ******************************************************************
LICENSE_END*/
package soccerscope.util.analyze;

import soccerscope.model.ClientScene;
import soccerscope.model.GameEvent;
import soccerscope.model.Param;
import soccerscope.model.PlayMode;
import soccerscope.util.geom.Line2f;
import soccerscope.util.geom.Point2f;
import soccerscope.util.geom.Vector2f;

public class ShootAnalyzer extends SceneAnalyzer {

	public static String NAME = "Shoot";

	private int ltime;

	private int lgoal;

	// private boolean lkick;

	private boolean lshoot;

	private int rtime;

	private int rgoal;

	// private boolean rkick;

	private boolean rshoot;

	@Override
	public void init() {
		super.init();
		this.ltime = 0;
		this.lgoal = 0;
		// this.lkick = false;
		this.lshoot = false;
		this.rtime = 0;
		this.rgoal = 0;
		// this.rkick = false;
		this.rshoot = false;
	}

	@Override
	public String getName() {
		return NAME;
	}

	@Override
	public GameEvent analyze(ClientScene clientScene, ClientScene prev) {
		GameEvent ge = null;

		if (this.lshoot) {
			if (clientScene.pmode.pmode == PlayMode.PM_AfterGoal_Left
					|| clientScene.pmode.pmode == PlayMode.PM_GoalKick_Right
					|| (clientScene.pmode.pmode == PlayMode.PM_FreeKick_Right && clientScene
							.isGoalieCatching())) {
				countUpLeft(this.ltime);
				ge = new GameEvent(this.ltime, GameEvent.SHOOT);
				this.lshoot = false;
			}
			for (int i = Param.MAX_PLAYER; i < Param.MAX_PLAYER * 2; i++) {
				if (clientScene.player[i].isKicking()
						|| clientScene.player[i].isTackling()) {
					if (inRightGoalArea(clientScene.player[i].pos)) {
						countUpLeft(this.ltime);
						this.lgoal++;
						ge = new GameEvent(this.ltime, GameEvent.SHOOT);
						this.lshoot = false;
					}
				}
			}
			if (clientScene.pmode.pmode == PlayMode.PM_TimeOver) {
				Line2f btraj = new Line2f(prev.ball.pos, clientScene.ball.pos);
				Line2f rightGoalLine = new Line2f(Param.topRightCorner,
						Param.bottomRightCorner);
				if (btraj.intersect(rightGoalLine)) {
					Point2f p = btraj.intersection(rightGoalLine);
					if (Math.abs(p.y) <= Param.GOAL_WIDTH / 2
							&& ((prev.ball.pos.x <= p.x && p.x <= clientScene.ball.pos.x) || (clientScene.ball.pos.x <= p.x && p.x <= prev.ball.pos.x))) {
						countUpLeft(this.ltime);
						this.lgoal++;
						ge = new GameEvent(this.ltime, GameEvent.SHOOT);
						this.lshoot = false;
					}
				}
			}
		}
		if (this.rshoot) {
			if (clientScene.pmode.pmode == PlayMode.PM_AfterGoal_Right
					|| clientScene.pmode.pmode == PlayMode.PM_GoalKick_Left
					|| (clientScene.pmode.pmode == PlayMode.PM_FreeKick_Left && clientScene
							.isGoalieCatching())) {
				countUpRight(this.rtime);
				ge = new GameEvent(this.rtime, GameEvent.SHOOT);
				this.rshoot = false;
			}
			for (int i = 0; i < Param.MAX_PLAYER; i++) {
				if (clientScene.player[i].isKicking()
						|| clientScene.player[i].isTackling()) {
					if (inLeftGoalArea(clientScene.player[i].pos)) {
						countUpRight(this.rtime);
						this.rgoal++;
						ge = new GameEvent(this.rtime, GameEvent.SHOOT);
						this.rshoot = false;
					}
				}
			}
			if (clientScene.pmode.pmode == PlayMode.PM_TimeOver) {
				Line2f btraj = new Line2f(prev.ball.pos, clientScene.ball.pos);
				Line2f leftGoalLine = new Line2f(Param.topLeftCorner,
						Param.bottomLeftCorner);
				if (btraj.intersect(leftGoalLine)) {
					Point2f p = btraj.intersection(leftGoalLine);
					if (Math.abs(p.y) <= Param.GOAL_WIDTH / 2
							&& ((prev.ball.pos.x <= p.x && p.x <= clientScene.ball.pos.x) || (clientScene.ball.pos.x <= p.x && p.x <= prev.ball.pos.x))) {
						countUpRight(this.rtime);
						this.rgoal++;
						ge = new GameEvent(this.rtime, GameEvent.SHOOT);
						this.rshoot = false;
					}
				}
			}
		}
		for (int i = 0; i < Param.MAX_PLAYER; i++) {
			if (clientScene.player[i].isKicking()) {
				// this.lkick = true;
				if (clientScene.ball.pos.dir(rightGoalTop) <= clientScene.ball.vel
						.th()
						&& clientScene.ball.pos.dir(rightGoalBottom) >= clientScene.ball.vel
								.th()) {
					Point2f pos = new Point2f();
					pos.add(clientScene.ball.pos, Vector2f
							.polar2vector(getFinalDist(
									clientScene.ball.vel.r(), 0.94f, 0.1f),
									clientScene.ball.vel.th()));
					if (pos.x >= 52.5) {
						this.lshoot = true;
						this.ltime = clientScene.time;
					}
				} else {
					this.lshoot = false;
				}
			}
		}
		for (int i = Param.MAX_PLAYER; i < Param.MAX_PLAYER * 2; i++) {
			if (clientScene.player[i].isKicking()) {
				// this.rkick = true;
				if (normalize(clientScene.ball.pos.dir(leftGoalTop)) >= normalize(clientScene.ball.vel
						.th())
						&& normalize(clientScene.ball.pos.dir(leftGoalBottom)) <= normalize(clientScene.ball.vel
								.th())) {
					Point2f pos = new Point2f();
					pos.add(clientScene.ball.pos, Vector2f
							.polar2vector(getFinalDist(
									clientScene.ball.vel.r(), 0.94f, 0.1f),
									clientScene.ball.vel.th()));
					if (pos.x <= -52.5) {
						this.rshoot = true;
						this.rtime = clientScene.time;
					}
				} else {
					this.rshoot = false;
				}
			}
		}

		return ge;
	}

	private static Point2f leftGoalTop = new Point2f(-52.5f, -8.16f);

	private static Point2f leftGoalBottom = new Point2f(-52.5f, 8.16f);

	private static Point2f rightGoalTop = new Point2f(52.5f, -8.16f);

	private static Point2f rightGoalBottom = new Point2f(52.5f, 8.16f);

	private boolean inLeftGoalArea(Point2f pos) {
		return -52.5f <= pos.x && pos.x <= -47.0f && -9.16 <= pos.y
				&& pos.y <= 9.16;
	}

	private boolean inRightGoalArea(Point2f pos) {
		return 47.0f <= pos.x && pos.x <= 52.5f && -9.16 <= pos.y
				&& pos.y <= 9.16;
	}
}
